﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Markup;

namespace WPFClient.Codes
{
    /// <summary>
    /// 滚筒线PLC数据处理类
    /// </summary>
    public static class RollerPLCDataLogic
    {
        #region 滚筒线报文数据转换

        /// <summary>
        /// 解析RollerPLC协议报文
        /// </summary>
        /// <param name="data">PLC发送的报文信息</param>
        /// <returns>返回序列化后的滚筒线报文数据对象</returns>
        /// <exception cref="ArgumentException">报文异常时的错误</exception>
        public static RollerPLCProtocolMessage RollerPLCDataParse(byte[] data)
        {
            if (data == null)
            {
                throw new ArgumentException("报文为空");
            }

            RollerPLCProtocolMessage message = new RollerPLCProtocolMessage();

            // 解析帧头 (字节0-1，小端序)
            message.FrameHeader = BitConverter.ToUInt16(data, 0);

            // 解析设备号 (字节2-3，小端序)
            message.DeviceId = BitConverter.ToUInt16(data, 2);

            // 解析任务号 (字节4-7，小端序) - 4字节
            message.TaskId = BitConverter.ToInt32(data, 4);

            // 解析备用字段 (字节8-9)
            message.Reserved = BitConverter.ToUInt16(data, 8);

            // 解析协议尾 (字节11-13) - 3字节FF FF FF
            // 字节10是固定00，不需要解析到对象中
            if (data[11] == 0xFF && data[12] == 0xFF && data[13] == 0xFF)
            {
                message.ProtocolTail = 0xFFFFFFFF;
            }
            else
            {
                throw new ArgumentException("协议尾校验失败");
            }

            return message;
        }

        /// <summary>
        /// 创建RollerPLC协议报文
        /// </summary>
        /// <param name="rollerPLCProtocolMessage">滚筒PLC报文协议对象</param>
        /// <returns>返回序列化后变为byte数组的报文信息</returns>
        public static byte[] CreateMessageToRollerPLC(RollerPLCProtocolMessage rollerPLCProtocolMessage)
        {
            byte[] data = new byte[14];

            // 帧头 (小端序)
            byte[] headerBytes = BitConverter.GetBytes(rollerPLCProtocolMessage.FrameHeader);
            Array.Copy(headerBytes, 0, data, 0, 2);

            // 设备号 (小端序)
            byte[] deviceBytes = BitConverter.GetBytes(rollerPLCProtocolMessage.DeviceId);
            Array.Copy(deviceBytes, 0, data, 2, 2);

            // 任务号 (小端序，4字节)
            byte[] taskBytes = BitConverter.GetBytes(rollerPLCProtocolMessage.TaskId);
            Array.Copy(taskBytes, 0, data, 4, 4);

            // 备用字段 (2字节)
            byte[] reservedBytes = BitConverter.GetBytes(rollerPLCProtocolMessage.Reserved);
            Array.Copy(reservedBytes, 0, data, 8, 2);

            // 固定00 (字节10)
            data[10] = 0x00;

            // 协议尾 (3字节FF FF FF)
            data[11] = 0xFF;
            data[12] = 0xFF;
            data[13] = 0xFF;

            return data;
        }

        #endregion
    }

    /// <summary>
    /// PLC协议解释器
    /// </summary>
    public static class PLCProtocolInterpreter
    {
        /// <summary>
        /// 协议类型
        /// </summary>
        public enum ProtocolType
        {
            Unknown,
            GenerateTask,           // 02 - 生成任务号
            GenerateDestination,    // 03 - 生成目的地
            ResetPhotoelectricError,// 102 - 复位光电异常
            TakePhotoSignal,        // 01 - 拍照信号
            DestinationConfirm,     // 04 - 目的地确认
            TaskComplete,           // 05 - 任务完成
            PhotoTimeout,           // 11 - 拍照超时
            DestinationTimeout,     // 12 - 目的地接收超时
            TaskLost,               // 13 - 任务丢失
            ChuteFull,              // 06 - 格口满箱
            ChuteNotFull,           // 07 - 格口解除满箱
            StartStop,              // 100 - 启停
            Alarm,                  // 101 - 报警
            Reset,                  // 102 - 复位
            PhotoelectricError,     // 102 - 光电异常
            ResetErrorComplete      // 103 - 复位异常完成
        }

        /// <summary>
        /// 根据帧头获取协议类型
        /// </summary>
        public static ProtocolType GetProtocolType(ushort frameHeader)
        {
            switch (frameHeader)
            {
                case 2: return ProtocolType.GenerateTask;
                case 3: return ProtocolType.GenerateDestination;
                case 102: return ProtocolType.ResetPhotoelectricError;
                case 1: return ProtocolType.TakePhotoSignal;
                case 4: return ProtocolType.DestinationConfirm;
                case 5: return ProtocolType.TaskComplete;
                case 11: return ProtocolType.PhotoTimeout;
                case 12: return ProtocolType.DestinationTimeout;
                case 13: return ProtocolType.TaskLost;
                case 6: return ProtocolType.ChuteFull;
                case 7: return ProtocolType.ChuteNotFull;
                case 100: return ProtocolType.StartStop;
                case 101: return ProtocolType.Alarm;
                //case 102: return ProtocolType.Reset; 文档这里重复了。
                case 103: return ProtocolType.ResetErrorComplete;
                default: return ProtocolType.Unknown;
            }
        }

        /// <summary>
        /// 获取协议描述
        /// </summary>
        public static string GetProtocolDescription(ProtocolType type)
        {
            switch (type)
            {
                case ProtocolType.GenerateTask: return "生成任务号";
                case ProtocolType.GenerateDestination: return "生成目的地";
                case ProtocolType.ResetPhotoelectricError: return "复位光电异常";
                case ProtocolType.TakePhotoSignal: return "拍照信号";
                case ProtocolType.DestinationConfirm: return "目的地确认";
                case ProtocolType.TaskComplete: return "任务完成";
                case ProtocolType.PhotoTimeout: return "拍照超时";
                case ProtocolType.DestinationTimeout: return "目的地接收超时";
                case ProtocolType.TaskLost: return "任务丢失";
                case ProtocolType.ChuteFull: return "格口满箱";
                case ProtocolType.ChuteNotFull: return "格口解除满箱";
                case ProtocolType.StartStop: return "启停信号";
                case ProtocolType.Alarm: return "报警信号";
                case ProtocolType.Reset: return "复位信号";
                case ProtocolType.PhotoelectricError: return "光电异常";
                case ProtocolType.ResetErrorComplete: return "复位异常完成";
                default: return "未知协议";
            }
        }

        /// <summary>
        /// 解析光电异常类型
        /// </summary>
        public static string ParsePhotoelectricError(long taskId)
        {
            if (taskId >= 1 && taskId <= 4)
            {
                switch (taskId)
                {
                    case 1: return "居中后光电异常";
                    case 2: return "分流口光电异常";
                    case 3: return "NG1光电异常";
                    case 4: return "NG2光电异常";
                }
            }
            else if (taskId >= 5 && taskId <= 14)
            {
                return string.Format("第一层第{0}个格口光电异常", taskId - 4);
            }
            else if (taskId >= 15 && taskId <= 24)
            {
                return string.Format("第二层第{0}个格口光电异常", taskId - 14);
            }

            return string.Format("未知光电异常 (ID: {0})", taskId);
        }

        /// <summary>
        /// 解析格口号
        /// </summary>
        public static string ParseChuteNumber(long taskId)
        {
            if (taskId == 41) return "NG1格口";
            if (taskId == 42) return "NG2格口";
            if (taskId >= 1 && taskId <= 40) return string.Format("第{0}号格口", taskId);

            return string.Format("未知格口 (ID: {0})", taskId);
        }
    }

    /// <summary>
    /// PLC消息处理器
    /// </summary>
    public class PLCMessageHandler
    {
        private readonly TCPHelper _tcpHelper;

        public event Action<string> LogMessageEvent;
        public event Action<string> ProtocolReceivedEvent;
        public event Action<long> TaskGeneratedEvent;
        public event Action<long> TaskCompletedEvent;

        public PLCMessageHandler(TCPHelper tcpHelper)
        {
            _tcpHelper = tcpHelper;
        }

        /// <summary>
        /// 启动监听
        /// </summary>
        public async Task StartListening()
        {
            await _tcpHelper.Connect(HandleReceivedData);
        }

        /// <summary>
        /// 处理接收到的数据
        /// </summary>
        private void HandleReceivedData(byte[] data, int length)
        {
            try
            {
                // 检查数据长度是否为16字节
                if (length != 16)
                {
                    LogMessage("数据长度不正确，应为16字节");
                    return;
                }

                var message = RollerPLCDataLogic.RollerPLCDataParse(data);

                if (!message.IsValidTail)
                {
                    LogMessage("协议尾校验失败");
                    return;
                }

                var protocolType = PLCProtocolInterpreter.GetProtocolType(message.FrameHeader);
                var description = PLCProtocolInterpreter.GetProtocolDescription(protocolType);

                string protocolInfo = string.Format("{0} | 设备号: {1} | 任务号: {2}",
                    description, message.DeviceId, message.TaskId);

                ProtocolReceivedEvent?.Invoke(protocolInfo);
                LogMessage("收到协议: " + protocolInfo);

                // 处理具体协议逻辑
                ProcessProtocolMessage(message, protocolType);
            }
            catch (Exception ex)
            {
                LogMessage("协议解析错误: " + ex.Message);
            }
        }

        /// <summary>
        /// 处理协议消息
        /// </summary>
        private void ProcessProtocolMessage(RollerPLCProtocolMessage message, PLCProtocolInterpreter.ProtocolType protocolType)
        {
            switch (protocolType)
            {
                case PLCProtocolInterpreter.ProtocolType.TakePhotoSignal:
                    TaskGeneratedEvent?.Invoke(message.TaskId);
                    LogMessage(string.Format("收到拍照信号，任务号: {0}", message.TaskId));
                    break;

                case PLCProtocolInterpreter.ProtocolType.TaskComplete:
                    TaskCompletedEvent?.Invoke(message.TaskId);
                    LogMessage(string.Format("任务完成，任务号: {0}", message.TaskId));
                    break;

                case PLCProtocolInterpreter.ProtocolType.PhotoelectricError:
                    string errorInfo = PLCProtocolInterpreter.ParsePhotoelectricError(message.TaskId);
                    LogMessage("光电异常: " + errorInfo);
                    break;

                case PLCProtocolInterpreter.ProtocolType.ChuteFull:
                    string chuteInfo = PLCProtocolInterpreter.ParseChuteNumber(message.TaskId);
                    LogMessage(chuteInfo + " 已满箱");
                    break;

                default:
                    LogMessage(string.Format("收到协议类型: {0}", protocolType));
                    break;
            }
        }

        /// <summary>
        /// 发送生成任务号指令
        /// </summary>
        public bool SendGenerateTask(long taskId, ushort deviceId = 1)
        {
            var message = new RollerPLCProtocolMessage
            {
                FrameHeader = 2,
                DeviceId = deviceId,
                TaskId = taskId,
                Reserved = 0,
                ProtocolTail = 0xFFFFFFFF
            };

            return SendMessage(message);
        }

        /// <summary>
        /// 发送消息到PLC
        /// </summary>
        private bool SendMessage(RollerPLCProtocolMessage message)
        {
            try
            {
                if (_tcpHelper.CurrentClient == null || !_tcpHelper.CurrentClient.Connected)
                {
                    LogMessage("TCP连接未建立");
                    return false;
                }

                byte[] data = RollerPLCDataLogic.CreateMessageToRollerPLC(message);
                NetworkStream stream = _tcpHelper.CurrentClient.GetStream();
                stream.Write(data, 0, data.Length);

                string protocolInfo = string.Format("发送: {0} | 任务号: {1}",
                    PLCProtocolInterpreter.GetProtocolDescription(PLCProtocolInterpreter.GetProtocolType(message.FrameHeader)),
                    message.TaskId);

                LogMessage(protocolInfo);
                return true;
            }
            catch (Exception ex)
            {
                LogMessage("发送消息失败: " + ex.Message);
                return false;
            }
        }

        /// <summary>
        /// 记录日志
        /// </summary>
        private void LogMessage(string message)
        {
            string formattedMessage = string.Format("{0:HH:mm:ss} - {1}", DateTime.Now, message);
            LogMessageEvent?.Invoke(formattedMessage);
        }

        /// <summary>
        /// 断开连接
        /// </summary>
        public void Disconnect()
        {
            _tcpHelper.Disconnect();
            LogMessage("已断开PLC连接");
        }
    }
}
